import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import random
import os
from config import dummy_data_dir


class CallBehaviorGenerator:
    """
    通话行为数据生成器
    
    根据用户入网信息生成符合真实通话模式的通话行为数据，包括：
    - 手机号、时间、对端号码、漫游类型、通话时长、费用
    - 支持套餐费用计算逻辑
    - 符合70%/25%/5%的通话频次分布
    """
    
    def __init__(self, user_data_path):
        """
        初始化生成器
        
        Args:
            user_data_path: 用户入网信息CSV文件路径
        """
        self.user_data = pd.read_csv(user_data_path)
        self.start_date = datetime(2024, 1, 1, 0, 0, 0)
        self.end_date = datetime(2024, 1, 14, 23, 59, 59)
        
        # 设置随机种子保证数据可重现
        np.random.seed(42)
        random.seed(42)
        
    def generate_phone_number(self, prefix=None):
        """生成对端手机号"""
        if prefix:
            return prefix + ''.join([str(random.randint(0, 9)) for _ in range(8)])
        else:
            prefixes = ['13', '15', '18', '17', '19']
            prefix = random.choice(prefixes)
            return prefix + ''.join([str(random.randint(0, 9)) for _ in range(9)])
    

    
    def generate_call_duration(self):
        """生成通话时长（分钟）"""
        # 真实通话时长分布：大部分1-5分钟，少量长通话
        rand = random.random()
        if rand < 0.6:
            return round(random.uniform(0.5, 5.0), 1)
        elif rand < 0.85:
            return round(random.uniform(5.0, 15.0), 1)
        elif rand < 0.95:
            return round(random.uniform(15.0, 30.0), 1)
        else:
            return round(random.uniform(30.0, 60.0), 1)
    
    def get_roaming_type(self, user_phone, daily_call_count, user_location):
        """根据用户位置和通话频次生成漫游类型
        
        规则：
        - 高频用户（每日通话次数>30次）中，50%的用户漫游类型为国际
        - 低频用户（每日通话次数≤30次）保持5%国际漫游概率
        - 同一用户的漫游类型保持一致（基于手机号种子）
        
        Args:
            user_phone: 用户手机号（用于一致性判断）
            daily_call_count: 每日通话次数
            user_location: 用户注册位置（备用，目前不影响判断）
            
        Returns:
            str: 漫游类型（"国内"或"国际"）
        """
        # 高频用户（通话次数>30次）中，50%用户的漫游类型为国际
        # 低频用户保持5%国际漫游概率
        if daily_call_count > 30:
            # 使用手机号作为种子，确保同一用户始终得到相同结果
            user_seed = int(''.join(filter(str.isdigit, str(user_phone))))
            random.seed(user_seed)
            is_international = random.random() < 0.5
            # 恢复全局随机种子
            random.seed(42)
            return "国际" if is_international else "国内"
        else:
            # 低频用户：5%国际漫游
            if random.random() < 0.05:
                return "国际"
            else:
                return "国内"
    
    def calculate_call_fee(self, duration, roaming_type, package_minutes, total_monthly_minutes):
        """
        计算通话费用
        
        Args:
            duration: 通话时长（分钟）
            roaming_type: 漫游类型
            package_minutes: 套餐包含分钟数
            total_monthly_minutes: 当月累计通话时长
            
        Returns:
            float: 通话费用
        """
        if roaming_type == "国际":
            # 国际漫游：3元/分钟
            return round(duration * 3.0, 2)
        else:
            # 国内通话：套餐内免费，超出0.15元/分钟
            if total_monthly_minutes <= package_minutes:
                return 0.0
            else:
                excess = min(duration, total_monthly_minutes - package_minutes)
                return round(excess * 0.15, 2)
    

    
    def generate_all_calls(self):
        """生成所有用户的通话行为数据"""
        all_calls = []
        
        # 获取所有手机号列表用于选择对端号码
        all_phone_numbers = [str(phone) for phone in self.user_data['Mobile Number'].tolist()]
        
        # 为每个用户确定其通话频次类型和漫游类型
        user_types = {}
        for _, user in self.user_data.iterrows():
            user_phone = str(user['Mobile Number'])
            # 根据分布规则确定用户类型
            rand = random.random()
            if rand < 0.7:  # 70%用户 - 低频
                call_count = random.randint(1, 10)
                user_type = 'low'
            elif rand < 0.95:  # 25%用户 - 中频
                call_count = random.randint(11, 30)
                user_type = 'medium'
            else:  # 5%用户 - 高频
                call_count = random.randint(31, 50)
                user_type = 'high'
            
            # 确定漫游类型
            if user_type == 'high':
                # 高频用户中50%为国际漫游
                user_seed = int(''.join(filter(str.isdigit, str(user_phone))))
                random.seed(user_seed)
                is_international = random.random() < 0.5
                random.seed(42)
                roaming_type = "国际" if is_international else "国内"
            else:
                # 低频和中频用户保持5%国际漫游
                roaming_type = "国际" if random.random() < 0.05 else "国内"
            
            user_types[user_phone] = {
                'daily_calls': call_count,
                'roaming_type': roaming_type,
                'user_type': user_type
            }
        
        for _, user in self.user_data.iterrows():
            user_phone = str(user['Mobile Number'])
            package_minutes = int(user.get('Free Call Minutes', 100))
            user_location = user.get('Registered Location', '北京')
            
            user_config = user_types[user_phone]
            daily_call_count = user_config['daily_calls']
            user_roaming_type = user_config['roaming_type']

            # 生成14天的通话记录
            user_monthly_minutes = 0
            user_daily_calls = []

            current_date = self.start_date
            while current_date <= self.end_date:
                daily_calls = []
                
                for _ in range(daily_call_count):
                    # 生成通话时间
                    hour = random.choice([
                        random.randint(8, 12),   # 上午
                        random.randint(13, 18),  # 下午
                        random.randint(19, 22)   # 晚上
                    ])
                    minute = random.randint(0, 59)
                    call_time = current_date.replace(hour=hour, minute=minute)

                    # 从CSV中选择对端号码（排除自身）
                    other_phone = random.choice([phone for phone in all_phone_numbers if phone != user_phone])
                    if not other_phone:  # 如果只有一个用户，使用生成的号码
                        other_phone = self.generate_phone_number()
                        while other_phone == user_phone:
                            other_phone = self.generate_phone_number()
                    
                    # 生成通话详情
                    duration = self.generate_call_duration()
                    
                    daily_calls.append({
                        'Mobile Number': user_phone,
                        'Timestamp': call_time.strftime('%Y-%m-%d %H:%M:%S'),
                        'Called Number': other_phone,
                        'Roaming Type': user_roaming_type,  # 使用用户固定的漫游类型
                        'Call Duration (Minutes)': duration,
                        'Cost (RMB)': 0.0  # 先设为0，后续统一计算
                    })
                
                # 计算当日总时长
                daily_total = sum(call['通话时长'] for call in daily_calls)
                user_monthly_minutes += daily_total
                
                # 更新费用
                for call in daily_calls:
                    call['费用'] = self.calculate_call_fee(
                        call['通话时长'],
                        call['漫游类型'],
                        package_minutes,
                        user_monthly_minutes
                    )
                
                user_daily_calls.extend(daily_calls)
                current_date += timedelta(days=1)
            
            all_calls.extend(user_daily_calls)
        
        return pd.DataFrame(all_calls)
    
    def save_to_csv(self, df, output_path):
        """保存通话行为数据到CSV文件"""
        df.to_csv(output_path, index=False, encoding='utf-8-sig')
        print(f"通话行为数据已保存至: {output_path}")
        print(f"数据概览:")
        print(f"- 总记录数: {len(df)}")
        print(f"- 用户数量: {df['Mobile Number'].nunique()}")
        print(f"- 时间范围: {df['Timestamp'].min()} 至 {df['Timestamp'].max()}")
        print(f"- 总费用: ¥{df['Cost (RMB)'].sum():.2f}")
        
        # 用户分布统计
        daily_counts = df.groupby('Mobile Number').size() / 14  # 14天
        low_users = (daily_counts <= 10).sum()
        medium_users = ((daily_counts > 10) & (daily_counts <= 30)).sum()
        high_users = (daily_counts > 30).sum()
        total_users = len(daily_counts)
        
        print(f"\n用户分布统计:")
        print(f"- 低频用户 (≤10次/日): {low_users} ({low_users/total_users*100:.1f}%)")
        print(f"- 中频用户 (11-30次/日): {medium_users} ({medium_users/total_users*100:.1f}%)")
        print(f"- 高频用户 (>30次/日): {high_users} ({high_users/total_users*100:.1f}%)")
        
        # 漫游类型分布
        roaming_stats = df['Roaming Type'].value_counts()
        domestic_calls = roaming_stats.get('国内', 0)
        international_calls = roaming_stats.get('国际', 0)
        total_calls = len(df)
        
        print(f"\n漫游类型分布:")
        print(f"- 国内通话: {domestic_calls} ({domestic_calls/total_calls*100:.1f}%)")
        print(f"- 国际漫游: {international_calls} ({international_calls/total_calls*100:.1f}%)")


def main():
    """主函数：生成通话行为数据"""
    # 文件路径
    user_data_path = os.path.join(dummy_data_dir, '用户入网信息表.csv').replace(os.sep, '/')
    output_path = os.path.join(dummy_data_dir, '通话行为表.csv').replace(os.sep, '/')
    
    # 检查输入文件是否存在
    if not os.path.exists(user_data_path):
        print(f"错误: 用户入网信息文件不存在: {user_data_path}")
        return
    
    # 创建生成器并生成数据
    generator = CallBehaviorGenerator(user_data_path)
    call_df = generator.generate_all_calls()
    
    # 保存结果（已包含统计信息输出）
    generator.save_to_csv(call_df, output_path)


if __name__ == "__main__":
    main()